#include "Submodule/Interface.h"
#include "Submodule/Version.h"
#include "Submodule/EffectItemGenerator.h"
#include "Submodule/MagicItemGenerator.h"
#include "Submodule/AffixFilter.h"
#include "Submodule/Generation.h"

#include "API/BSTypes/BSStringT.h"
#include "API/TESForms/TESObject.h"

#define DEFINE_INTFC_GET(type, cmnd, retn) \
	retn SubmoduleInterface::Get ## type ## cmnd ## (TESForm* form) { \
		type ## * ptr = dynamic_cast<type ## *>(form); \
		if ( !ptr ) return false; \
	/*	_MESSAGE( "[%08X]->Get" #type #cmnd , ptr->formID); \
	*/	return ptr->Get ## cmnd ## (); \
	}

#define DEFINE_INTFC_SET(type, cmnd, vtype) \
	bool SubmoduleInterface::Set ## type ## cmnd ## (TESForm* form, vtype val) { \
		type ## * ptr = dynamic_cast<type ## *>(form); \
		if ( !ptr ) return false; \
	/*	_MESSAGE("[%08X]->Set" #type #cmnd ## , ptr->formID); \
	*/	return ptr->Set ## cmnd ## (val); \
	}

#define DEFINE_INTFC_PAIR(type, cmnd, retval) \
	DEFINE_INTFC_GET(type, cmnd, retval) \
	DEFINE_INTFC_SET(type, cmnd, retval)

#define DEFINE_INTFC_GET_NTH(type, cmnd, retn) \
	retn SubmoduleInterface::Get ## type ## Nth ## cmnd ## (TESForm* form, UInt32 n) { \
		type ## * ptr = dynamic_cast<type ## *>(form); \
		if ( !ptr ) return false; \
	/*	_MESSAGE("[%08X]->Get" #type "Nth" #cmnd , ptr->formID); \
	*/	return ptr->GetNth ## cmnd ## (n); \
	}

#define DEFINE_INTFC_SET_NTH(type, cmnd, vtype) \
	bool SubmoduleInterface::Set ## type ## Nth ## cmnd ## (TESForm* form, UInt32 n, vtype val) { \
		type ## * ptr = dynamic_cast<type ## *>(form); \
		if ( !ptr ) return false; \
	/*	_MESSAGE("[%08X]->Get" #type "Nth" #cmnd , ptr->formID); \
	*/	return ptr->SetNth ## cmnd ## (n, val); \
	}

#define DEFINE_INTFC_PAIR_NTH(type, cmnd, retval) \
	DEFINE_INTFC_GET_NTH(type, cmnd, retval);\
	DEFINE_INTFC_SET_NTH(type, cmnd, retval)

void SubmoduleInterface::ListMyForms()
{
    // dumps info on all MyForm objects in the extended data handler to the output log
    // the list is accessed using the FormList() method of the MyForm::extendedForm object
    _MESSAGE("Dumping MyForm List ...");
    gLog.Indent();
    for (BSSimpleList<TESForm*>::Node* node = &MagicItemGenerator::extendedForm.FormList().firstNode; node && node->data; node = node->next)
    {
        MagicItemGenerator* mig = (MagicItemGenerator*)node->data;
        _MESSAGE("MagicItemGenerator %02X '%s' (%08X): type='%s'",
            mig->GetFormType(), mig->GetEditorID(), mig->formID, 
            mig->suf?"Suffix":"Prefix");
    }
    gLog.Outdent();
}
const char* SubmoduleInterface::Description()
{
    static char buffer[0x100];
    sprintf_s(buffer,sizeof(buffer), SOLUTIONNAME ", v%i.%i beta%i", MAJOR_VERSION,MINOR_VERSION,BETA_VERSION);
    return buffer;
}

DEFINE_INTFC_PAIR	(MagicItemGenerator, IsSuffix,		bool		);
DEFINE_INTFC_PAIR	(MagicItemGenerator, MinUses,		UInt16		);
DEFINE_INTFC_PAIR	(MagicItemGenerator, MaxUses,		UInt16		);
DEFINE_INTFC_PAIR	(MagicItemGenerator, Rank,			SInt16		);
DEFINE_INTFC_PAIR	(MagicItemGenerator, Frequency,		UInt8		);
DEFINE_INTFC_PAIR	(MagicItemGenerator, IsAutocalc,	bool		);
DEFINE_INTFC_GET	(MagicItemGenerator, AffixMask,		UInt8		);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixSubpetty,	const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixPetty,	const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixLesser,	const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixCommon,	const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixGreater,	const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixGrand,	const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator,AffixUltragrand,const char*	);
DEFINE_INTFC_PAIR	(MagicItemGenerator, AffixNegative,	const char*	);

DEFINE_INTFC_GET	(AffixFilter,		NumAffixes,		UInt32		);
bool SubmoduleInterface::AffixFilterAddAffix(TESForm* form, TESForm* new_mig, UInt8 soul) {
	AffixFilter* flt = dynamic_cast<AffixFilter*>(form);
	MagicItemGenerator* mig = dynamic_cast<MagicItemGenerator*>(new_mig);
	if ( !flt || !mig ) return false;
	_MESSAGE("[%08X]->AffixFilterAddAffix", flt);
	return flt->AddAffix(mig, soul);
}
bool SubmoduleInterface::AffixFilterDeleteNthAffix(TESForm* form, UInt32 n) {
	AffixFilter* flt = dynamic_cast<AffixFilter*>(form);
	if ( !flt ) return false;
	_MESSAGE("[%08X]->AffixFilterAddAffix", flt);
	return flt->DeleteNthAffix(n);
}
	
DEFINE_INTFC_GET_NTH(AffixFilter,		AffixMagicItemGenerator,UInt32);
bool SubmoduleInterface::SetAffixFilterNthAffixMagicItemGenerator(TESForm* form, UInt32 n, TESForm* new_mig) {
	AffixFilter* flt = dynamic_cast<AffixFilter*>(form);
	MagicItemGenerator* mig = dynamic_cast<MagicItemGenerator*>(new_mig);
	if ( !flt || !mig ) return false;
	_MESSAGE("[%08X]->AffixFilterAddAffix", flt);
	return flt->SetNthAffixMagicItemGenerator(n, mig);
}
DEFINE_INTFC_PAIR_NTH	(AffixFilter,	AffixMask,		UInt8		);
	
DEFINE_INTFC_PAIR	(AffixFilter,		NameFilter,		const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		MinValue,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxValue,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MinWeight,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxWeight,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MinDurability,	double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxDurability,	double		);

DEFINE_INTFC_PAIR	(AffixFilter,		ApparelMask,	UInt8		);
DEFINE_INTFC_PAIR	(AffixFilter,		MinArmorRating,	double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxArmorRating,	double		);
DEFINE_INTFC_PAIR	(AffixFilter,		HidesRings,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		HidesAmulet,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedHead,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedHair,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedBodyLower,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedBodyUpper,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedHand,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedFoot,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedRingLeft,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedRingRight,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedAmulet,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedWeapon,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedWeaponBack,int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedWeaponSide,int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedQuiver,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedShield,	int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedTorch,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		BipedTail,		int			);
DEFINE_INTFC_PAIR	(AffixFilter,		ModelFilterBipedMale,	const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		ModelFilterBipedFemale,	const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		ModelFilterGroundMale,	const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		ModelFilterGroundFemale,const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		IconFilterMale,			const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		IconFilterFemale,		const char*	);
	
DEFINE_INTFC_PAIR	(AffixFilter,		WeaponMask,		UInt8		);
DEFINE_INTFC_PAIR	(AffixFilter,		MinDamage,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxDamage,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MinReach,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxReach,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MinSpeed,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		MaxSpeed,		double		);
DEFINE_INTFC_PAIR	(AffixFilter,		IgnoresNormalWeaponResistance,	int	);
DEFINE_INTFC_PAIR	(AffixFilter,		ModelFilterWeapon,		const char*	);
DEFINE_INTFC_PAIR	(AffixFilter,		IconFilterWeapon,		const char*	);

std::vector< std::pair<UInt32, UInt32> >* SubmoduleInterface::GeneratedItemList() const {
#ifdef OBLIVION
	return &Generation::generatedItems;
#else
	return NULL;
#endif
}

TESForm* SubmoduleInterface::Enchant(TESForm* form, UInt16 level, bool LtEq /*=true*/) const {
#ifdef OBLIVION
	TESBoundObject* obj = dynamic_cast<TESBoundObject*>(form);
	if ( obj )
		return static_cast<TESForm*>(Generation::Enchant(obj, level, LtEq));
	else
#endif
		return NULL;
}
